// sql_create.h

#ifndef _SQL_CREATE_CPP_
#define _SQL_CREATE_CPP_


// #include"../include/utils.h"
#include"sql_create.h"


//规整主码同步性
void SQL_Create::confirm_PrimaryKeys(DBInfo::TableInfo& result_tb){
    result_tb.PriKeys.clear();
    std::vector<DBInfo::Attribute>& lis = result_tb.AttrList;
    int lenth = lis.size();
    int push_cnt = 0;
    for(int i=0;i<lenth;i++){
        DBInfo::Attribute& rhs = lis[i];
        if(rhs.pri_key){
            result_tb.PriKeys.push_back(rhs.col_name);
            push_cnt++;
        }
    }
    if(push_cnt == 0){
        //没有主码的警告
        printf("[warn]-SQL_Create::confirm_PrimaryKeys():statements has no primary keys\n");
    }
}

//解析主码
//成功:0
//失败:-1
int SQL_Create::parse_PrimaryKeys(std::string line,DBInfo::TableInfo& result_tb){
    std::vector<std::string> res;
    //获取匹配字段
    res = SavenUtils::RegexSearch(line,"\\bprimary\\s+key\\s*\\([^()]+\\)");
    int len = res.size();
    if(len != 1){
        printf("[error]-SQL_Create::parse_PrimaryKeys():Find multi primary key statements\n");
        return -1;
    }
    std::string content = res[0];
    res = SavenUtils::RegexSearch(line,"(?<=\\()[^()]+(?=\\))");
    if(res.size() != 1){
        printf("[error]-SQL_Create::parse_PrimaryKeys():Statements get-element error\n");
        return -1;
    }
    content = res[0];
    //获取各个主码名称
    content += ",";
    // printf("pri_line:[%s]\n",content.c_str());
    res.clear();
    for(int i=0;i<100;i++){//防止陷入死循环
        if(content == "") break;
        std::string pre = SavenUtils::trim(SavenUtils::Split_first(content,","));
        if(pre == "") break;
        content = SavenUtils::trim(SavenUtils::Split_second(content,","));
        res.push_back(pre);
    }
    //主码验证与注册
    len = res.size();
    //获取属性列表引用
    std::vector<DBInfo::Attribute>& attrlist = result_tb.AttrList;
    int lenth = attrlist.size();
    for(int i=0;i<len;i++){
        //逐个主码属性存在性验证
        std::string& rhs = res[i];
        // printf("one_pri:[%s]\n",rhs.c_str());
        int flag_not_ok = 1;
        for(int k=0;k<lenth;k++){
            //遍历属性
            DBInfo::Attribute& one_attr = result_tb.AttrList[k];
            if(one_attr.col_name == rhs){
                flag_not_ok = 0;
                //注册主码属性信息
                result_tb.PriKeys.push_back(one_attr.col_name);
                one_attr.pri_key = true;
                one_attr.data_not_null = true;
                break;
            }
        }
        if(flag_not_ok){
            printf("[error]-SQL_Create::parse_PrimaryKeys():Primary Statements error\n");
            return -1;
        }
    }
    //主码统一性验证
    //保证全表声明与列声明中的主码是同步的
    std::vector<std::string> lis;
    for(int i=0;i<lenth;i++){
        DBInfo::Attribute& one_attr = result_tb.AttrList[i];
        if(one_attr.pri_key){
            lis.push_back(one_attr.col_name);
        }
    }
    std::sort(lis.begin(),lis.end());
    std::sort(res.begin(),res.end());
    if(lis == res){
        if(lis.size() == 0){
            //没有主码警告
            printf("[warn]-SQL_Create::parse_PrimaryKeys():Statements has no primary keys\n");
        }
        return 0;
    }
    printf("[error]-SQL_Create::parse_PrimaryKeys():Primary Statements not-same\n");
    return -1;
}

//解析并设置外码信息
//成功:0
//失败:-1
int SQL_Create::parse_ForeignKeys(std::string line,DBInfo::TableInfo& result_tb){
    std::vector<std::string> res;
    //获取参照属性名
    res = SavenUtils::RegexSearch(line,"(?<=foreign key\\()\\s*[a-zA-Z0-9\\_]+\\s*(?=\\) reference)\\s*");
    int len = res.size();
    // printf("len = %d\n",len);
    if(res.size() != 1){
        printf("[error]-SQL_Create::parse_ForeignKeys():Get-ForeignName error size\n");
        return -1;
    }
    std::string ref_name = res[0];//参照属性名
    //获取参照属性段
    line = SavenUtils::trim(line);
    if(line[line.size()-1] != ',') { line+=","; }
    res = SavenUtils::RegexSearch(line,"(?<=references ).+(?=,)");
    if(res.size() != 1){
        printf("[error]-SQL_Create::parse_ForeignKeys():Get-ForeignSegment error\n");
        return -1;
    }
    std::string ref_seg_strs = res[0];//参照属性段
    // printf("ref_seg:%s\n",ref_seg_strs.c_str());
    std::string ref_table = SavenUtils::Split_first(ref_seg_strs,"(");//被参照属性所属的表
    ref_table = SavenUtils::trim(ref_table);
    //获取被参照的属性名
    res = SavenUtils::RegexSearch(ref_seg_strs,"(?<=\\()\\s*[^()]+\\s*(?=\\))");
    if(res.size() != 1){
        printf("[error]-SQL_Create::parse_ForeignKeys():Get-ForeignSegment error\n");
        return -1;
    }
    std::string ref_attr_name = res[0];

    //找到响应的外码属性
    int lenth = result_tb.AttrList.size();
    int index = -1;
    for(int i=0;i<lenth;i++){
        DBInfo::Attribute& rhs = result_tb.AttrList[i];
        if(rhs.col_name == ref_name){
            index = i;
        }
    }
    //参照不成立
    if(index < 0){
        printf("[error]-SQL_Create::parse_ForeignKeys():Reference not-correct\n");
        return -1;
    }
    DBInfo::Attribute& rhs = result_tb.AttrList[index];
    // rhs.show();
    //把获取到的信息写入对象
    rhs.ref_tbname = ref_table;
    rhs.ref_col_name = ref_attr_name;
    rhs.ref_key = true;
    return 0;
}

//解析并获取特别声明属性
// input:单个属性的描述行及其Attribute变量的引用 保证line小写
int SQL_Create::parse_DataAttrs(std::string line,DBInfo::Attribute& result_attr){
    //获取基本属性
    std::vector<std::string> res = SavenUtils::RegexSearch(line,"(unique|not null|primary key)");
    int cnt = res.size();
    for(int i=0;i<cnt;i++){
        if(res[i] == "unique"){
            //唯一属性
            result_attr.data_unique = true;
        }else if(res[i] == "not null"){
            //非空属性
            result_attr.data_not_null = true;
        }else if(res[i] == "primary key"){
            //主码声明
            result_attr.pri_key = true;
            //主码一定not null
            result_attr.data_not_null = true;
        }
    }
    return 0;
}

//解析并获取属性类型
// 成功 0/1 1表示设置的数据类型可能存在数据限制
// 失败 -1 未发现数据类型的声明语句
int SQL_Create::parse_DataType(std::string line,DBInfo::Attribute& result_attr){
    result_attr.data_type = Meta::Type::TYPE_UNKNOW;
    // printf("line:%s\n",line.c_str());
    //获取基本属性
    std::vector<std::string> res = SavenUtils::RegexSearch(line,"(long|char|int|double|varchar)");
    int lenth = res.size();
    if(lenth != 1){
        printf("[error]-SQL_Create::parse_DataType():Data-type error lenth=%d\n",lenth);
        return -1;
    }
    //设置属性值
    std::string ty = res[0];
    //发现可能存在限制的类型
    int flag = 0;
    if(ty == "long"){
        result_attr.data_type = Meta::Type::TYPE_LONG;
    }else if(ty == "char"){
        result_attr.data_type = Meta::Type::TYPE_CHAR;
        flag = 1;
    }else if(ty == "int"){
        result_attr.data_type = Meta::Type::TYPE_INT;
    }else if(ty == "double"){
        result_attr.data_type = Meta::Type::TYPE_DOUBLE;
    }else if(ty == "varchar"){
        result_attr.data_type = Meta::Type::TYPE_VARCHAR;
        flag = 1;
    }else{//未定义类型
        printf("[report]-SQL_Create::parse_DataType():Data-type unknow\n");
    }
    return flag;
}

//获取限制大小
// 成功:0获取限制 1未检测到限制
// 失败:-1 多个定义字段错误
// 失败:-2 定义字段内限制的解析错误
int SQL_Create::get_LimitInt(std::string line,DBInfo::Attribute& result_attr){
    // printf("attribute:%s\n",result_attr.col_name.c_str());
    // //限制存在检测
    // if(false == SavenUtils::RegexMatch(line,"\\b(long|char|int|double|varchar)\\s*\\(\\s*[0-9]+\\s*\\)")){
    //     printf("no limit here\n\n");
    //     return 1;//匹配表明:未声明限制
    // }
    //获取类型定义段
    std::vector<std::string> res = SavenUtils::RegexSearch(line,"\\b(long|char|int|double|varchar)\\s*\\(\\s*[0-9]+\\s*\\)");
    if(res.size() != 1){
        printf("[error]-SQL_Create::get_LimitInt():define multi error\n");
        return -1;
    }
    // printf("limit get size = %d\n\n",(int)res.size());
    line = res[0];
    //获取限制大小
    res = SavenUtils::RegexSearch(line,"(?<=\\()\\s*[0-9]+\\s*(?=\\))");
    if(res.size() != 1){
        printf("[error]-SQL_Create::get_LimitInt():define multi limit error\n");
        return -2;
    }
    result_attr.data_type_limit = SavenUtils::String2Int(res[0]);
    return 0;
}

//解析所有属性值
//成功:0
//失败:-1
int SQL_Create::parse_Attributes(std::vector<std::string>& rhs,DBInfo::TableInfo& result_tb){
    result_tb.AttrList.clear();//清空原有所有的属性值
    int lenth = rhs.size();
    for(int i=0;i<lenth;i++){
        int ret = 0;
        std::string line = rhs[i];
        line = SavenUtils::StringtoLower(line);//设置小写
        DBInfo::Attribute oneattr;
        //解析获取属性名
        oneattr.col_name = SavenUtils::trim(SavenUtils::Split_first(SavenUtils::trim(line)," "));
        //解析获取属性类型
        ret = SQL_Create::parse_DataType(line,oneattr);
        if(ret < 0){
            printf("[error]-SQL_Create::parse_Attributes():Data-type Parse Error\n");
            continue;
        }
        //解析获取属性限制
        // printf("before get_limit ret = %d\n",(int)ret);
        if(ret == 1){ 
            ret = get_LimitInt(line,oneattr);
            if(ret < 0){
                printf("[error]-SQL_Create::parse_Attributes():Get_Atrribute error\n");
                return -1;
            }
        }
        //解析获取属性特别声明
        SQL_Create::parse_DataAttrs(line,oneattr);
        //添加属性值
        result_tb.AttrList.push_back(oneattr);
    }
    return 0;
}



/* !!!!! */
// 通过解析一个crete table语句获取表的信息
// 成功:0 表信息位于result_tb中
// 失败:-1 create语句不合法 不支持多行解析
int SQL_Create::create_table(const std::string order,DBInfo::TableInfo& result_tb){
    std::string line = order;
    //输入语句去首位空格
    line = SavenUtils::trim(line);
    //检查尾部分号
    int lenth = line.size();
    if(line[lenth-1] != ';'){
        line += ";";
        lenth++;
    }
    //检查create语句基本合法性
    if(SavenUtils::RegexMatch(line,"^(create table).+\\(.+(\\);)$")){
        //获取table名称
        std::vector<std::string> res = SavenUtils::RegexSearch(line,"(?<=create table )\\s*[a-zA-Z0-9\\_]+(?=\\s*\\()");
        if(res.size() == 1){
            result_tb.tbname = res[0];
        }else{
            printf("[error]-SQL_Create::create_table():multi-tablename\n");
            return -1;
        }
        //获取括号内的定义句子
        res = SavenUtils::RegexSearch(line,"(?<= \\().+(?=\\));?");
        if(res.size() != 1){
            printf("[error]-SQL_Create::create_table():multi-content\n");
            return -1;
        }
        //加逗号
        std::string content = res[0] + ",";

        //获取外码语句
        res = SavenUtils::RegexSearch(content,"foreign key\\s*\\([^()]*\\)\\s*references\\s*[^()]*\\([^()]*\\)\\s*,");
        //外码语句集合-个数任意 可以没有
        std::vector<std::string> foreign_lines = res;
        //删除外码语句
        content = SavenUtils::RegexDelete(content,"foreign key\\s*\\([^()]*\\)\\s*references\\s*[^()]*\\([^()]*\\)\\s*,");

        //获取主码定义语句-最多一句主码定义语句
        res = SavenUtils::RegexSearch(content,"primary key\\s*\\([^()]*\\),");
        //主码定义语句-最多有一个
        std::string primary_line = res.size() == 0 ? "" : res[0];
        //删除主码定义语句
        content = SavenUtils::RegexDelete(content,"primary key\\s*\\([^()]*\\),");
        // printf("content:[%s]\n",content.c_str());
        //句子拆分
        // res = SavenUtils::RegexSearch(content,"[^,]+?(?=,)");
        res.clear();
        for(int tt=0;tt<100;tt++){
            std::string one = SavenUtils::Split_first(content,",");
            if(one == "")break;
            content = SavenUtils::Split_second(content,",");
            res.push_back(one);
        }
        if(res.size() == 0){
            printf("[error]-SQL_Create::create_table():not define table\n");
            return -1;
        }
        //解析属性值
        // printf("属性个数:%d\n",(int)res.size());
        int ret = SQL_Create::parse_Attributes(res,result_tb);
        if(ret < 0){
            printf("[error]-SQL_Create::create_table():parse_Attributes error\n");
            return -1;
        }
        // printf("sdfasdsfa\n");
        //外码解析
        if(foreign_lines.size() == 1){
            ret = SQL_Create::parse_ForeignKeys(foreign_lines[0],result_tb);
            // printf("asdfasgasdgn\n");
            if(ret < 0){
                printf("[error]-SQL_Create::create_table():parse_ForeignKeys error\n");
                return -1;
            }
        }
        //主码解析
        if(primary_line != ""){
            ret = SQL_Create::parse_PrimaryKeys(primary_line,result_tb);
            if(ret < 0){
                printf("[error]-SQL_Create::create_table():parse_PrimaryKeys error\n");
                return -1;
            }
        }else{
            //主码整理
            SQL_Create::confirm_PrimaryKeys(result_tb);
        }
        //解析完成
        return 0;
    }
    printf("[error]-SQL_Create::create_table():CREATE not match\n");
    return -1;
}




#endif // _SQL_CREATE_CPP_

